<template>
  <div class="image-compress-tool">
    <div class="tool-header">
      <h1>图片压缩工具</h1>
      <p>快速压缩图片文件，减小文件大小</p>
    </div>

    <div class="tool-container">
      <el-row :gutter="20">
        <!-- 上传区域 -->
        <el-col :span="12">
          <div class="upload-section">
            <div class="section-header">
              <h3>上传图片</h3>
            </div>
            
            <div class="upload-area">
              <el-upload
                ref="uploadRef"
                class="upload-dragger"
                drag
                :auto-upload="false"
                :show-file-list="false"
                :on-change="handleFileChange"
                accept="image/*"
              >
                <el-icon class="el-icon--upload"><upload-filled /></el-icon>
                <div class="el-upload__text">
                  将图片拖到此处，或<em>点击上传</em>
                </div>
                <template #tip>
                  <div class="el-upload__tip">
                    支持 JPG、PNG、GIF、WebP 格式，单个文件不超过 10MB
                  </div>
                </template>
              </el-upload>
            </div>
            
            <div class="file-info" v-if="originalFile">
              <h4>原始文件信息</h4>
              <div class="info-grid">
                <div class="info-item">
                  <span class="label">文件名：</span>
                  <span class="value">{{ originalFile.name }}</span>
                </div>
                <div class="info-item">
                  <span class="label">文件大小：</span>
                  <span class="value">{{ formatFileSize(originalFile.size) }}</span>
                </div>
                <div class="info-item">
                  <span class="label">图片尺寸：</span>
                  <span class="value">{{ originalImageSize }}</span>
                </div>
                <div class="info-item">
                  <span class="label">格式：</span>
                  <span class="value">{{ originalFile.type }}</span>
                </div>
              </div>
            </div>
          </div>
        </el-col>

        <!-- 压缩设置和结果 -->
        <el-col :span="12">
          <div class="compress-section">
            <div class="section-header">
              <h3>压缩设置</h3>
            </div>
            
            <div class="compress-options" v-if="originalFile">
              <div class="option-group">
                <label>压缩质量：</label>
                <el-slider
                  v-model="quality"
                  :min="10"
                  :max="100"
                  :step="5"
                  show-input
                  :show-input-controls="false"
                />
                <div class="quality-tips">
                  <span class="tip-item" :class="{ active: quality >= 90 }">高质量</span>
                  <span class="tip-item" :class="{ active: quality >= 70 && quality < 90 }">中等质量</span>
                  <span class="tip-item" :class="{ active: quality < 70 }">高压缩</span>
                </div>
              </div>
              
              <div class="option-group">
                <label>输出格式：</label>
                <el-radio-group v-model="outputFormat">
                  <el-radio label="original">保持原格式</el-radio>
                  <el-radio label="jpeg">JPEG</el-radio>
                  <el-radio label="png">PNG</el-radio>
                  <el-radio label="webp">WebP</el-radio>
                </el-radio-group>
              </div>
              
              <div class="option-group">
                <label>最大尺寸：</label>
                <el-input-number
                  v-model="maxWidth"
                  :min="100"
                  :max="4000"
                  controls-position="right"
                  placeholder="宽度"
                />
                <span class="separator">×</span>
                <el-input-number
                  v-model="maxHeight"
                  :min="100"
                  :max="4000"
                  controls-position="right"
                  placeholder="高度"
                />
                <el-button @click="resetSize" size="small" type="info">重置</el-button>
              </div>
            </div>
            
            <div class="compress-actions" v-if="originalFile">
              <el-button 
                type="primary" 
                @click="compressImage"
                :loading="isCompressing"
                size="large"
              >
                <el-icon><Download /></el-icon>
                开始压缩
              </el-button>
              <el-button @click="resetAll" size="large">重置</el-button>
            </div>
            
            <!-- 压缩结果 -->
            <div class="result-section" v-if="compressedFile">
              <div class="section-header">
                <h3>压缩结果</h3>
              </div>
              
              <div class="result-info">
                <div class="comparison">
                  <div class="comparison-item">
                    <h4>压缩前</h4>
                    <div class="file-size">{{ formatFileSize(originalFile.size) }}</div>
                  </div>
                  <div class="comparison-item">
                    <h4>压缩后</h4>
                    <div class="file-size">{{ formatFileSize(compressedFile.size) }}</div>
                  </div>
                </div>
                
                <div class="compression-stats">
                  <el-tag type="success" size="large">
                    压缩率: {{ compressionRatio }}%
                  </el-tag>
                  <el-tag type="info" size="large">
                    节省: {{ savedSize }}
                  </el-tag>
                </div>
              </div>
              
              <div class="result-actions">
                <el-button @click="downloadCompressed" type="primary" size="large">
                  <el-icon><Download /></el-icon>
                  下载压缩图片
                </el-button>
                <el-button @click="previewImage" size="large">
                  <el-icon><View /></el-icon>
                  预览图片
                </el-button>
              </div>
            </div>
          </div>
        </el-col>
      </el-row>

      <!-- 使用说明 -->
      <div class="tool-info">
        <el-card>
          <template #header>
            <div class="card-header">
              <span>使用说明</span>
            </div>
          </template>
          
          <div class="info-content">
            <h4>图片压缩原理：</h4>
            <p>通过调整图片质量、尺寸和格式来减小文件大小，同时保持图片的视觉效果。</p>
            
            <h4>压缩建议：</h4>
            <ul>
              <li><strong>高质量（90-100%）：</strong>适合打印或高质量展示</li>
              <li><strong>中等质量（70-89%）：</strong>适合网页显示，平衡质量和大小</li>
              <li><strong>高压缩（10-69%）：</strong>适合缩略图或快速加载</li>
            </ul>
            
            <h4>格式选择：</h4>
            <ul>
              <li><strong>JPEG：</strong>适合照片，压缩效果好</li>
              <li><strong>PNG：</strong>适合图标和透明图片</li>
              <li><strong>WebP：</strong>现代格式，压缩率更高</li>
            </ul>
            
            <h4>注意事项：</h4>
            <div class="warning">
              <p>⚠️ 压缩是单向操作，无法恢复原始质量</p>
              <p>⚠️ 建议先备份原始图片</p>
              <p>⚠️ 压缩后的图片仅在前端处理，不会上传到服务器</p>
            </div>
          </div>
        </el-card>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'
import { ElMessage } from 'element-plus'
import { UploadFilled, Download, View } from '@element-plus/icons-vue'

const uploadRef = ref()
const originalFile = ref(null)
const compressedFile = ref(null)
const originalImageSize = ref('')
const quality = ref(80)
const outputFormat = ref('original')
const maxWidth = ref(1920)
const maxHeight = ref(1080)
const isCompressing = ref(false)

const handleFileChange = (file) => {
  const fileObj = file.raw
  if (!fileObj) return
  
  // 检查文件类型
  if (!fileObj.type.startsWith('image/')) {
    ElMessage.error('请选择图片文件')
    return
  }
  
  // 检查文件大小
  if (fileObj.size > 10 * 1024 * 1024) {
    ElMessage.error('文件大小不能超过10MB')
    return
  }
  
  originalFile.value = fileObj
  
  // 获取图片尺寸
  const img = new Image()
  img.onload = () => {
    originalImageSize.value = `${img.width} × ${img.height}`
    maxWidth.value = img.width
    maxHeight.value = img.height
  }
  img.src = URL.createObjectURL(fileObj)
  
  ElMessage.success('图片上传成功')
}

const compressImage = async () => {
  if (!originalFile.value) {
    ElMessage.warning('请先上传图片')
    return
  }
  
  isCompressing.value = true
  
  try {
    // 模拟压缩过程
    await new Promise(resolve => setTimeout(resolve, 1000))
    
    const canvas = document.createElement('canvas')
    const ctx = canvas.getContext('2d')
    const img = new Image()
    
    img.onload = () => {
      // 计算压缩后的尺寸
      let { width, height } = calculateCompressedSize(img.width, img.height)
      
      canvas.width = width
      canvas.height = height
      
      // 绘制压缩后的图片
      ctx.drawImage(img, 0, 0, width, height)
      
      // 获取压缩后的数据
      const format = getOutputFormat()
      const mimeType = `image/${format}`
      
      canvas.toBlob((blob) => {
        compressedFile.value = blob
        isCompressing.value = false
        ElMessage.success('图片压缩完成')
      }, mimeType, quality.value / 100)
    }
    
    img.src = URL.createObjectURL(originalFile.value)
  } catch (error) {
    isCompressing.value = false
    ElMessage.error('压缩失败：' + error.message)
  }
}

const calculateCompressedSize = (originalWidth, originalHeight) => {
  let width = originalWidth
  let height = originalHeight
  
  // 如果超过最大尺寸，按比例缩放
  if (width > maxWidth.value || height > maxHeight.value) {
    const ratio = Math.min(maxWidth.value / width, maxHeight.value / height)
    width = Math.floor(width * ratio)
    height = Math.floor(height * ratio)
  }
  
  return { width, height }
}

const getOutputFormat = () => {
  if (outputFormat.value === 'original') {
    return originalFile.value.type.split('/')[1] || 'jpeg'
  }
  return outputFormat.value
}

const formatFileSize = (bytes) => {
  if (bytes === 0) return '0 Bytes'
  const k = 1024
  const sizes = ['Bytes', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

const compressionRatio = computed(() => {
  if (!originalFile.value || !compressedFile.value) return 0
  return Math.round((1 - compressedFile.value.size / originalFile.value.size) * 100)
})

const savedSize = computed(() => {
  if (!originalFile.value || !compressedFile.value) return '0 Bytes'
  return formatFileSize(originalFile.value.size - compressedFile.value.size)
})

const downloadCompressed = () => {
  if (!compressedFile.value) {
    ElMessage.warning('没有可下载的文件')
    return
  }
  
  const url = URL.createObjectURL(compressedFile.value)
  const a = document.createElement('a')
  a.href = url
  a.download = `compressed_${originalFile.value.name}`
  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
  URL.revokeObjectURL(url)
  
  ElMessage.success('文件下载开始')
}

const previewImage = () => {
  if (!compressedFile.value) {
    ElMessage.warning('没有可预览的文件')
    return
  }
  
  const url = URL.createObjectURL(compressedFile.value)
  window.open(url, '_blank')
}

const resetSize = () => {
  if (originalFile.value) {
    const img = new Image()
    img.onload = () => {
      maxWidth.value = img.width
      maxHeight.value = img.height
    }
    img.src = URL.createObjectURL(originalFile.value)
  }
}

const resetAll = () => {
  originalFile.value = null
  compressedFile.value = null
  originalImageSize.value = ''
  quality.value = 80
  outputFormat.value = 'original'
  maxWidth.value = 1920
  maxHeight.value = 1080
  uploadRef.value?.clearFiles()
  ElMessage.info('已重置所有设置')
}
</script>

<style scoped>
.image-compress-tool {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
}

.tool-header {
  text-align: center;
  margin-bottom: 40px;
}

.tool-header h1 {
  font-size: 2.5rem;
  color: #333;
  margin-bottom: 10px;
}

.tool-header p {
  color: #666;
  font-size: 1.1rem;
}

.tool-container {
  margin-bottom: 40px;
}

.upload-section,
.compress-section {
  background: white;
  border-radius: 12px;
  padding: 24px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
  border: 1px solid #f0f0f0;
  height: 100%;
}

.section-header {
  margin-bottom: 20px;
}

.section-header h3 {
  color: #333;
  margin: 0;
  font-size: 1.3rem;
}

.upload-area {
  margin-bottom: 20px;
}

.upload-dragger {
  width: 100%;
}

.file-info {
  background: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #e9ecef;
}

.file-info h4 {
  margin: 0 0 15px 0;
  color: #333;
  font-size: 1.1rem;
}

.info-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.info-item {
  display: flex;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid #e9ecef;
}

.info-item:last-child {
  border-bottom: none;
}

.label {
  font-weight: 500;
  color: #666;
}

.value {
  color: #333;
  font-family: 'Courier New', monospace;
}

.compress-options {
  margin-bottom: 30px;
}

.option-group {
  margin-bottom: 25px;
}

.option-group label {
  display: block;
  margin-bottom: 10px;
  font-weight: 500;
  color: #333;
}

.quality-tips {
  display: flex;
  justify-content: space-between;
  margin-top: 10px;
}

.tip-item {
  padding: 4px 8px;
  border-radius: 4px;
  font-size: 0.8rem;
  color: #666;
  background: #f0f0f0;
}

.tip-item.active {
  background: #667eea;
  color: white;
}

.separator {
  margin: 0 10px;
  color: #666;
}

.compress-actions {
  display: flex;
  gap: 12px;
  margin-top: 30px;
}

.result-section {
  margin-top: 30px;
  padding: 20px;
  background: #f8f9fa;
  border-radius: 8px;
  border: 1px solid #e9ecef;
}

.result-info {
  margin-bottom: 20px;
}

.comparison {
  display: flex;
  justify-content: space-around;
  margin-bottom: 20px;
}

.comparison-item {
  text-align: center;
}

.comparison-item h4 {
  margin: 0 0 10px 0;
  color: #333;
}

.file-size {
  font-size: 1.2rem;
  font-weight: bold;
  color: #667eea;
}

.compression-stats {
  display: flex;
  justify-content: center;
  gap: 15px;
}

.result-actions {
  display: flex;
  gap: 12px;
  justify-content: center;
}

.tool-info {
  margin-top: 40px;
}

.card-header {
  font-weight: bold;
  color: #333;
}

.info-content h4 {
  color: #333;
  margin: 20px 0 10px 0;
  font-size: 1.1rem;
}

.info-content p {
  color: #666;
  line-height: 1.6;
  margin-bottom: 15px;
}

.info-content ul {
  color: #666;
  padding-left: 20px;
  margin-bottom: 15px;
}

.info-content li {
  margin-bottom: 5px;
}

.warning {
  background: #fff3cd;
  padding: 15px;
  border-radius: 8px;
  border-left: 4px solid #ffc107;
  margin: 15px 0;
}

.warning p {
  margin: 5px 0;
  color: #856404;
}

@media (max-width: 768px) {
  .tool-header h1 {
    font-size: 2rem;
  }
  
  .info-grid {
    grid-template-columns: 1fr;
  }
  
  .comparison {
    flex-direction: column;
    gap: 15px;
  }
  
  .compression-stats {
    flex-direction: column;
    align-items: center;
  }
  
  .result-actions {
    flex-direction: column;
  }
}
</style>
